package com.java.gps.socket;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SocketServer {
    public static void main(String[] args) throws Exception {
        // 监听指定的端口
        int port = 55533;
        ServerSocket server = new ServerSocket(port);
        // server将一直等待连接的到来
        System.out.println("server将一直等待连接的到来");

        //如果使用多线程，那就需要线程池，防止并发过高时创建过多线程耗尽资源
        ExecutorService executor = Executors.newFixedThreadPool(10);

        while (true) {
            Socket socket = server.accept();

            Runnable runnable = () -> {
                try {
                    // 建立好连接后，从socket中获取输入流，并建立缓冲区进行读取
                    InputStream inputStream = socket.getInputStream();
                    // 以追加的形式写true
                    FileOutputStream fos = new FileOutputStream("D:/a.txt", true);
                    byte[] bytes;
                    // 因为可以复用Socket且能判断长度，所以可以一个Socket用到底
                    while (true) {
                        // 首先读取两个字节表示的长度
                        int first = inputStream.read();
                        //如果读取的值为-1 说明到了流的末尾，Socket已经被关闭了，此时将不能再去读取
                        if (first == -1) {
                            break;
                        }
                        int second = inputStream.read();
                        int length = (first << 8) + second;
                        // 然后构造一个指定长的byte数组
                        bytes = new byte[length];
                        // 然后读取指定长度的消息即可
                        inputStream.read(bytes);
                        // 写入到文件
                        fos.write(bytes, 0, length);
                        fos.flush();
                        System.out.println(Thread.currentThread().getId() + ": get message from client: " + new String(bytes, "UTF-8"));
                    }
                    inputStream.close();
                    socket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
            executor.execute(runnable);
        }
    }
}